<?php
/**
 * Create by PhpStorm
 * User: mozongyou
 * Date: 2021/8/17
 * Time: 8:43 下午
 */
/**
 *
 * ${PARAM_DOC}
 * @return ${TYPE_HINT}
 * ${THROWS_DOC}
 * @author mozongyou
 * @date 2021-08-17 8:43 下午
 */
declare(strict_types=1);

namespace App\Service\WebSocket;
//连接id管理
class FdService
{
    /**
     * 存放所有fd的列表
     * @var array
     */
    private $_fdList = [];

    /**
     * 存放房间fd列表
     * @var array
     */
    private $_roomFdList = [];

    /** 用户id绑定fd的列表
     * @var array
     */
    private $_userBindFdList = [];

    /**
     * 心跳列表
     * @var array
     */
    private $_heartbeatList = [];

    private static $_instance;

    private function __construct()
    {
    }

    public static function getInstance()
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * 把fd放进列表中
     * @param $fd
     * @author mozongyou
     * @date 2021-08-18 7:18 下午
     */
    public function putFdList($fd)
    {
        $this->_fdList[$fd] = $fd;
    }

    /**
     * 获取fd列表
     * @return array
     * @author mozongyou
     * @date 2021-08-18 7:19 下午
     */
    public function getFdList()
    {
        return $this->_fdList;
    }

    /**
     * 清除无效的fd
     * @param $fd
     * @author mozongyou
     * @date 2021-08-18 7:29 下午
     */
    public function clearFd($fd)
    {
        if (!empty($this->_fdList[$fd])) {
            unset($this->_fdList[$fd]);
        }
    }

    /**
     * 绑定房间
     * @param $fd
     * @param $roomId
     * @author mozongyou
     * @date 2021-08-18 7:58 下午
     */
    public function bindRoom($fd, $roomId)
    {
        if (in_array($fd, $this->getRoomFdList($roomId))) {
            return;
        }
        $this->_roomFdList[$roomId][$fd] = $fd;
    }

    /**
     * 获取单个房间的fd列表
     * @param $roomId
     * @return array
     * @author mozongyou
     * @date 2021-08-18 8:07 下午
     */
    public function getRoomFdList($roomId)
    {
        return $this->_roomFdList[$roomId] ?? [];
    }

    /**
     * 清除单个房间里面包含该fd的数据
     * @param $fd
     * @param $roomId
     * @author mozongyou
     * @date 2021-09-26 9:39 上午
     */
    public function clearRoomFd($fd, $roomId)
    {
        if (!empty($this->getRoomFdList($roomId)[$fd])) {
            unset($this->getRoomFdList($roomId)[$fd]);
        }
    }

    /**
     * 清除所有房间里面包含该fd的数据
     * @param $fd
     * @author mozongyou
     * @date 2021-09-26 11:10 上午
     */
    public function clearAllRoomFd($fd)
    {
        if (!empty($this->_roomFdList)) {
            foreach ($this->_roomFdList as $roomId => $fdList) {
                if (!empty($this->_roomFdList[$roomId][$fd])) {
                    unset($this->_roomFdList[$roomId][$fd]);
                }
            }
        }
    }

    /**
     * 绑定用户
     * @param $fd
     * @param $uid
     * @author mozongyou
     * @date 2021-08-18 8:22 下午
     */
    public function bindUser($fd, $uid)
    {
        if (empty($uid)) {
            return;
        }
        $this->_userBindFdList[$uid] = $fd;
    }

    /**
     * 获取用户绑定列表
     * @return array
     * @author mozongyou
     * @date 2021-08-18 8:24 下午
     */
    public function getUserBindFdList()
    {
        return $this->_userBindFdList;
    }

    /**
     * 清除绑定用户fd
     * @param $fd
     * @param $uid
     * @author mozongyou
     * @date 2021-09-26 10:45 上午
     */
    public function clearUserFd($fd, $uid = 0)
    {
        if (empty($uid)) {
            if ($key = array_search($fd, $this->_userBindFdList)) {
                unset($this->_userBindFdList[$key]);
            }
        } else {
            if (!empty($this->_userBindFdList[$uid])) {
                unset($this->_userBindFdList[$uid]);
            }
        }

    }

    /**
     * 获取心跳检测列表
     * @return array
     * @author mozongyou
     * @date 2021-09-25 4:30 下午
     */
    public function getHeartbeatList()
    {
        return $this->_heartbeatList;
    }

    /**
     * 设置心跳时间
     * @param $fd
     * @author mozongyou
     * @date 2021-09-25 4:36 下午
     */
    public function setHeartbeat($fd)
    {
        $this->_heartbeatList[$fd] = [
            'fd' => $fd,
            'time' => time()
        ];
    }

    /**
     * 清除某个链接的心跳
     * @param $fd
     * @author mozongyou
     * @date 2021-09-25 5:17 下午
     */
    public function clearHeartbeat($fd)
    {
        if (!empty($this->_heartbeatList[$fd])) {
            unset($this->_heartbeatList[$fd]);
        }
    }

    /**
     * 清除所有包含该fd的数据
     * @param $fd
     * @author mozongyou
     * @date 2021-09-26 11:12 上午
     */
    public function clearData($fd)
    {
        $this->clearFd($fd);
        $this->clearHeartbeat($fd);
        $this->clearUserFd($fd);
        $this->clearAllRoomFd($fd);
    }

    private function __clone()
    {
    }
}